package com.zxs.seckillweb.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zxs.constant.Constants;
import com.zxs.entity.Goods;
import com.zxs.entity.Orders;
import com.zxs.entity.Users;
import com.zxs.seckillweb.service.impl.GoodsServiceImpl;
import com.zxs.seckillweb.service.impl.LuaService;
import com.zxs.vo.HttpResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Tag(name = "秒杀商品API接口管理")
@Controller
@Slf4j
public class GoodsController {

    @Resource
    private GoodsServiceImpl goodsService;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private LuaService luaService;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private ObjectMapper objectMapper;

    /**
     * 商品列表
     * @return
     */
    @GetMapping("/goods/list")
    public ModelAndView goodsList() {
        List<Goods> goodsList = goodsService.getGoodsList();

        ModelAndView modelAndView = new ModelAndView("list");
        modelAndView.addObject("goodsList", goodsList);

        return modelAndView;
    }

    /**
     * 通过商品详情，获取商品详细信息
     *
     * @param goodsId 商品ID
     * @return
     */
    @GetMapping("/goods/{id}")
    public ModelAndView goodsDetail(@PathVariable("id") Integer goodsId) {
        Goods goodsDetail = goodsService.getGoodsDetail(goodsId);
        goodsDetail.setRandomName(null);
        ModelAndView modelAndView = new ModelAndView("detail");
        modelAndView.addObject("goods", goodsDetail);
        modelAndView.addObject("nowTime", new Date());

        return modelAndView;
    }


    /**
     * 获取秒杀商品路径的随机码
     *
     * @param goodsId 商品ID
     * @return
     */
    @Operation(summary = "获取随机码")
    @GetMapping("/goods/time/{id}")
    @ResponseBody
    public HttpResult getRandomName(@PathVariable("id") Integer goodsId, HttpServletRequest  request) {

        //模拟一下已经登录了，后面会用到
        Users users = Users.builder().id(20030211).name("thomas").phone("13700000000").build();
        request.getSession().setAttribute(Constants.LOGIN_USER, users);

        HttpResult httpResult = new HttpResult();

        //获取商品详情
        Goods goodsDetail = goodsService.getGoodsDetail(goodsId);

        //秒杀开始时间
        long startTime = goodsDetail.getStartTime().getTime();
        //秒杀结束时间
        long endTime = goodsDetail.getEndTime().getTime();

        //获取当前时间  判断秒杀是否开始
        long currentTime = new Date().getTime();

        //判断当前时间是否在秒杀时间段内
        if (currentTime >= startTime && currentTime <= endTime) {
            httpResult.setCode(0);
            httpResult.setData(goodsDetail.getRandomName());
            httpResult.setMsg("秒杀进行中");
            return httpResult;
        }

        httpResult.setCode(-1);
        httpResult.setMsg("秒杀未开始");
        httpResult.setData(null);
        return httpResult;
    }


    @PostMapping("/goods/{id}/{random}")
    @ResponseBody
    public HttpResult doSeckill(@PathVariable("id") Integer goodsId,@PathVariable("random") String random,HttpServletRequest request) throws JsonProcessingException {
    //1、判断秒杀是否开始
        Goods goodsDetail =(Goods) redisTemplate.opsForValue().get(Constants.REDIS_GOODS + goodsId);
        //1.1获取秒杀开始时间
        long startTime = goodsDetail.getStartTime().getTime();
        //1.2获取秒杀结束时间
        long endTime = goodsDetail.getEndTime().getTime();
        //1.3获取当前时间
        long currentTime = new Date().getTime();
        if (currentTime < startTime) {
            return HttpResult.builder().code(Constants.ERROR).msg("秒杀未开始").build();
        }
        if (currentTime > endTime) {
            return HttpResult.builder().code(Constants.ERROR).msg("秒杀已结束").build();
        }

    //2.判断携带的商品随机值是否正确
        if (!goodsDetail.getRandomName().equals(random)) {
            //携带的随机值不一致
            return HttpResult.builder().code(Constants.ERROR).msg("请求不合法").build();
        }

    //3.判断库存....下单
        if (goodsDetail.getStore() <= 0) {
            //库存不足
            return HttpResult.builder().code(Constants.ERROR).msg("商品已经被抢光~~~").build();
        }

        //下单  涉及到线程安全问题，因为是多线程  都去操作库存要去修改库存，可能会导致超卖问题
        //使用lua脚本进行操作
        //获取用户信息
        Users users =(Users) request.getSession().getAttribute(Constants.LOGIN_USER);
        //Users users = Users.builder().id(20030211).name("zxs").phone("18888888888").build();
        //调用luaService执行lua脚本
        Long runLuaResult = luaService.runLuaScript(String.valueOf(goodsDetail.getId()), String.valueOf(users.getId()));

        System.out.println("runLuaResult = " + runLuaResult);

        if (runLuaResult == -1) {
            return HttpResult.builder().code(Constants.ERROR).msg("您已经秒杀过该商品了，不能再秒杀了").build();
        }
        if (runLuaResult == -2) {
            return HttpResult.builder().code(Constants.ERROR).msg("服务器太拥挤了，没有挤进去~").build();
        }
        if (runLuaResult == -3) {
            return HttpResult.builder().code(Constants.ERROR).msg("商品已经抢光了~~~").build();
        }

        Orders orders = Orders.builder()
                .uid(users.getId())
                .goodsId(goodsDetail.getId())
                .buyNum(1)
                .buyPrice(goodsDetail.getPrice())
                .orderMoney(goodsDetail.getPrice().multiply(new BigDecimal(1)))
                .createTime(new Date())
                .updateTime(new Date())
                .status(Constants.ORDER_STATUS_WAITPAY)
                .build();
        String jsonOrders = objectMapper.writeValueAsString(orders);
        Message message = new Message(jsonOrders.getBytes());
        rabbitTemplate.convertAndSend(Constants.EXCHANGE_NAME_ORDER,Constants.ROUTING_KEY_ORDER,message);
        log.info("成功发送订单消息!!!");
        return HttpResult.builder().code(Constants.SUCCESS).msg("秒杀请求提交成功，正在处理，请稍候......").build();

    }

    /**
     * 查询秒杀结果
     * @param goodsId 商品ID
     * @return
     */
    @GetMapping("/goods/result/{id}")
    @ResponseBody
    public HttpResult getResult(@PathVariable("id") Integer goodsId,HttpServletRequest request) {
        Users user =(Users) request.getSession().getAttribute(Constants.LOGIN_USER);
        Orders orders = goodsService.getResult(goodsId,user.getId());
        if (orders != null) {
            if (orders.getStatus() == Constants.ORDER_STATUS_TIMEOUT) {
                return HttpResult.builder().code(Constants.TIMEOUT).msg("支付超时，订单已经被关闭").data(orders).build();
            }
            return HttpResult.builder().code(Constants.SUCCESS).msg("抢购成功").data(orders).build();
        }
        return HttpResult.builder().code(Constants.ERROR).msg("抢购失败").data(null).build();
    }

}
